﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

using Prism.Core;
using Prism.Core.WPF;
using Prism.Games.GalEngine.Scripts.Parser.Input;

namespace Prism.Games.GalEngine.Scripts.Parser
{
    public class SaveDataManager
    {
        public const string SaveFolder = GameFrameLibrary.Strings.SaveFolder;

        public const string SystemDataDat = GameFrameLibrary.Strings.SystemData;

        public SaveDataManager()
        {
            this.Datas = new GalSaveDataCollection();
            this.SystemData = new GalSystemSaveData();

            this.CheckSaveData();

        }

        public void CheckSaveData()
        {
            var folder = SaveFolder;

            if (Directory.Exists(folder))
            {
                var files = Directory.GetFiles(folder);
                var bf = new BinaryFormatter();
                if (files.Count() != 0)
                {
                    this.Datas.Clear();
                    foreach (var i in files)
                    {
                        using (var fs = new FileStream(i, FileMode.Open))
                        {
                            try
                            {
                                var target = bf.Deserialize(fs) as GalSaveData;
                                if (target != null)
                                    this.AddData(target);
                            }
                            catch (Exception ex)
                            {
                                System.Windows.MessageBox.Show(ex.Message);
                                continue;
                            }
                        }
                    }
                    var q = from i in files
                            where Path.GetFileName(i) == GameFrameLibrary.Strings.SystemData
                            select i;
                    if (q.Count() == 0)
                    {
                        foreach (var i in Helper.Script.Sections)
                        {
                            foreach (var j in i.Scenes)
                            {
                                var target = j as FunctionModel.IReaderLogable;
                                target.IsRead = false;
                            }
                        }
                    }
                    else if (q.Count() == 1)
                    {
                        var i = q.Single();
                        using (var fs = new FileStream(i, FileMode.Open))
                        {
                            try
                            {
                                this.SystemData = bf.Deserialize(fs) as GalSystemSaveData;

                                if (Helper.Script.GameName != this.SystemData.Script.GameName || Helper.Script.Version != this.SystemData.Script.Version)
                                {
                                    System.Windows.MessageBox.Show(GameFrameLibrary.Strings.SystemDataErrorWarring);
                                    System.Windows.Application.Current.Shutdown();
                                }

                                Helper.Script = this.SystemData.Script;
                            }
                            catch (Exception ex)
                            {
                                System.Windows.MessageBox.Show(ex.Message);
                                return;
                            }
                        }
                    }
                    else return;
                }
            }
        }

        public GalSaveDataCollection Datas { get; set; }

        public GalSystemSaveData SystemData { get; set; }

        public ParserState SaveState { get; set; }

        public System.Windows.Media.Imaging.BitmapSource CurrentShotCut { get; protected set; }

        public void TakeShotCut(System.Windows.FrameworkElement element)
        {
            this.CurrentShotCut = element.CreateBitmapSource();
        }

        public GalSaveData Save(int postion)
        {
            var data = new GalSaveData();
            data.CreateTime = DateTime.Now;
            data.GameName = Helper.Script.GameName;
            data.Version = Helper.Script.Version;
            data.State = this.SaveState;
            data.Comment = "";
            data.CanWrite = true;
            data.ShotCut = this.CurrentShotCut;
            data.Postion = postion;
            //
            Helper.MemoryDataStore.OnStoreRoles(Helper.Script.Resource.Roles, data.Roles);

            return data;
        }

        public void AddData(GalSaveData data)
        {
            var q = from i in this.Datas
                    where i.Postion == data.Postion
                    select i;
            if (q.Count() == 1)
            {
                this.Datas.Remove(q.Single());
            }
            this.Datas.Add(data);
        }

        public void SaveSystemData()
        {
            var target = Path.Combine(SaveFolder, SystemDataDat);

            var folder = SaveFolder;

            if (!Directory.Exists(folder))
            {
                Directory.CreateDirectory(folder);
            }

            using (var fs = new FileStream(target, FileMode.Create))
            {
                var bf = new BinaryFormatter();

                this.SystemData.Script = Helper.Script;

                try
                {
                    bf.Serialize(fs, this.SystemData);
                }
                catch (Exception ex)
                {
                    System.Windows.MessageBox.Show(ex.Message);
                    System.Windows.Application.Current.Shutdown();
                }
            }
        }

        public void Load(GalSaveData data)
        {
            if (data.GameName != Helper.Script.GameName)
            {
                System.Windows.MessageBox.Show(GameFrameLibrary.Strings.SaveDataGameNameError);
                return;
            }
            if (data.Version != Helper.Script.Version)
            {
                System.Windows.MessageBox.Show(GameFrameLibrary.Strings.SaveDataVersionError);
                return;
            }

            Helper.MemoryDataStore.OnRoleReset(Helper.Script.Resource.Roles, data.Roles);

            var q = from i in Helper.Script.Sections
                    where i.Id == data.State.Section.Id
                    select i;
            var section = q.Single();
            Helper.Parser.CurrentState.Section = section;

            var q2 = from i in section.Scenes
                     where i.Id == data.State.Scene.Id
                     select i;
            var scene = q2.Single();
            Helper.Parser.CurrentState.Scene = scene;

            Helper.Parser.CurrentState.IsEnd = false;

            this.IsJustFromLoad = true;

            Helper.Parser.StartCurrent();
        }

        public bool IsJustFromLoad = false;
    }
}
